# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: xguo

import threading
import time

from coin.base.atomic import AtomicLong
from coin.base.timestamp import get_timestamp


class RequestNonceManager(object):
  def __init__(self, *, init_nonce=None, request_gap_sec=None):
    self._last_request_timestamp = None
    self._request_gap = None
    self._request_lock = threading.Lock()

    if init_nonce is None:
      self._nonce = AtomicLong(int(time.time() * 1000000))
    else:
      assert isinstance(init_nonce, AtomicLong)
      self._nonce = init_nonce

    if request_gap_sec and request_gap_sec > 1e-5:
      self._request_gap = request_gap_sec * 1e9

  def busy_wait_if_necessary(self):
    if self._request_gap is None:
      return

    if self._last_request_timestamp is None:
      self._last_request_timestamp = get_timestamp()
      return

    while True:
      with self._request_lock:
        elapsed_time = get_timestamp() - self._last_request_timestamp
        if elapsed_time > self._request_gap:
          self._last_request_timestamp = get_timestamp()
          break

  def get_nonce(self):
    self.busy_wait_if_necessary()
    return self._nonce.get_and_add(1)
